// lib/redisUtil.ts
import redisConnection from './redis-client';
import type { Redis } from 'ioredis';
import { stringify, parse } from 'superjson';

/**
 * 泛型 Redis 工具类
 */
class RedisUtil {
  private client: Redis;

  constructor() {
    this.client = redisConnection.getClient();
  }

  // =============================================================================
  // 🔹 通用操作
  // =============================================================================
  /**
   * 判断 key 是否存在
   */
  async exists(key: string): Promise<boolean> {
    const count = await this.client.exists(key);
    return count > 0;
  }

  /**
   * 删除一个或多个 key
   */
  async del(...keys: string[]): Promise<number> {
    return this.client.del(...keys);
  }

  /**
   * 设置过期时间
   */
  async expire(key: string, seconds: number): Promise<number> {
    return this.client.expire(key, seconds);
  }
  // =============================================================================
  // 🔸 String 操作（已在前面实现，保留）
  // =============================================================================

  async set<T>(key: string, value: T, ttl?: number): Promise<'OK'> {
    const serialized = stringify(value);
    if (ttl !== undefined) {
      return this.client.setex(key, ttl, serialized);
    }
    return this.client.set(key, serialized);
  }

  async get<T>(key: string): Promise<T | null> {
    const data = await this.client.get(key);
    if (data === null) return null;
    try {
      return parse(data) as T;
    } catch (err) {
      console.error('[Redis] 反序列化失败:', err);
      return null;
    }
  }

  // =============================================================================
  // 🔸 Hash 操作
  // =============================================================================

  /**
   * 获取 hash 中所有字段和值
   */
  async hgetall<T extends Record<string, any>>(key: string): Promise<T | null> {
    const data = await this.client.hgetall(key);
    if (Object.keys(data).length === 0) return null;
    try {
      const parsed: Record<string, any> = {};
      for (const [field, val] of Object.entries(data)) {
        parsed[field] = parse(val);
      }
      return parsed as T;
    } catch (err) {
      console.error('[Redis] Hash 反序列化失败:', err);
      return null;
    }
  }

  /**
   * 获取 hash 中指定字段的值
   */
  async hget<T>(key: string, field: string): Promise<T | null> {
    const data = await this.client.hget(key, field);
    if (data === null) return null;
    try {
      return parse(data) as T;
    } catch (err) {
      console.error('[Redis] Hash 字段反序列化失败:', err);
      return null;
    }
  }

  /**
   * 设置 hash 中一个字段的值
   */
  async hset<T>(key: string, field: string, value: T): Promise<number> {
    const serialized = stringify(value);
    return this.client.hset(key, field, serialized);
  }

  /**
   * 批量设置 hash 中多个字段
   */
  async hmset(key: string, values: Record<string, any>): Promise<'OK'> {
    const serialized: Record<string, string> = {};
    for (const [field, val] of Object.entries(values)) {
      serialized[field] = stringify(val);
    }
    return this.client.hmset(key, serialized);
  }

  /**
   * 删除 hash 中一个或多个字段
   */
  async hdel(key: string, ...fields: string[]): Promise<number> {
    return this.client.hdel(key, ...fields);
  }

  /**
   * 判断 hash 中某个字段是否存在
   */
  async hexists(key: string, field: string): Promise<boolean> {
    const exists = await this.client.hexists(key, field);
    return exists === 1;
  }

  // =============================================================================
  // 🔸 Set 操作
  // =============================================================================

  /**
   * 向集合添加一个或多个成员
   */
  async sadd(key: string, ...values: any[]): Promise<number> {
    const serialized = values.map(v => stringify(v));
    return this.client.sadd(key, ...serialized);
  }

  /**
   * 移除集合中的一个或多个成员
   */
  async srem(key: string, ...values: any[]): Promise<number> {
    const serialized = values.map(v => stringify(v));
    return this.client.srem(key, ...serialized);
  }

  /**
   * 判断成员是否是集合的成员
   */
  async sismember<T>(key: string, value: T): Promise<boolean> {
    const serialized = stringify(value);
    const isMember = await this.client.sismember(key, serialized);
    return isMember === 1;
  }

  /**
   * 返回集合的所有成员
   */
  async smembers<T>(key: string): Promise<T[]> {
    const members = await this.client.smembers(key);
    return members.map(data => {
      try {
        return parse(data) as T;
      } catch {
        return null;
      }
    }).filter((item): item is T => item !== null);
  }

  /**
   * 返回集合的成员数
   */
  async scard(key: string): Promise<number> {
    return this.client.scard(key);
  }

  // =============================================================================
  // 🔸 List 操作
  // =============================================================================

  /**
   * 将一个或多个值插入到列表头部
   */
  async lpush(key: string, ...values: any[]): Promise<number> {
    const serialized = values.map(v => stringify(v));
    return this.client.lpush(key, ...serialized);
  }

  /**
   * 将一个或多个值插入到列表尾部
   */
  async rpush(key: string, ...values: any[]): Promise<number> {
    const serialized = values.map(v => stringify(v));
    return this.client.rpush(key, ...serialized);
  }

  /**
   * 获取列表指定范围内的元素
   */
  async lrange<T>(key: string, start = 0, stop = -1): Promise<T[]> {
    const items = await this.client.lrange(key, start, stop);
    return items.map(data => {
      try {
        return parse(data) as T;
      } catch {
        return null;
      }
    }).filter((item): item is T => item !== null);
  }

  /**
   * 移出并获取列表的第一个元素
   */
  async lpop<T>(key: string): Promise<T | null> {
    const data = await this.client.lpop(key);
    if (data === null) return null;
    try {
      return parse(data) as T;
    } catch {
      return null;
    }
  }

  /**
   * 移出并获取列表的最后一个元素
   */
  async rpop<T>(key: string): Promise<T | null> {
    const data = await this.client.rpop(key);
    if (data === null) return null;
    try {
      return parse(data) as T;
    } catch {
      return null;
    }
  }

  /**
   * 获取列表长度
   */
  async llen(key: string): Promise<number> {
    return this.client.llen(key);
  }

  // =============================================================================
  // 🔸 Sorted Set (ZSet) 操作
  // =============================================================================

  /**
   * 向有序集合添加一个或多个成员，或者更新已存在成员的分数
   */
  async zadd(key: string, values: { score: number; value: any }[]): Promise<number> {
    const args: Array<string | number> = [];
    for (const item of values) {
      args.push(item.score);
      args.push(stringify(item.value));
    }
    return this.client.zadd(key, ...args);
  }

  /**
   * 返回有序集合中指定分数区间的成员
   */
  async zrange<T>(key: string, start: number, stop: number): Promise<T[]> {
    const members = await this.client.zrange(key, start, stop);
    return members.map(data => {
      try {
        return parse(data) as T;
      } catch {
        return null;
      }
    }).filter((item): item is T => item !== null);
  }

  /**
   * 返回有序集合中指定分数区间的所有成员，按分数递减（从高到低）排列
   */
  async zrevrange<T>(key: string, start: number, stop: number): Promise<T[]> {
    const members = await this.client.zrevrange(key, start, stop);
    return members.map(data => {
      try {
        return parse(data) as T;
      } catch {
        return null;
      }
    }).filter((item): item is T => item !== null);
  }

  /**
   * 移除有序集合中的一个或多个成员
   */
  async zrem(key: string, ...values: any[]): Promise<number> {
    const serialized = values.map(v => stringify(v));
    return this.client.zrem(key, ...serialized);
  }

  /**
   * 获取有序集合的成员数量
   */
  async zcard(key: string): Promise<number> {
    return this.client.zcard(key);
  }

  /**
   * 返回有序集中成员的分数值
   */
  async zscore(key: string, value: any): Promise<number | null> {
    const serialized = stringify(value);
    const score = await this.client.zscore(key, serialized);
    return score ? parseFloat(score) : null;
  }

  /**
   * 返回有序集中成员的排名（升序）
   */
  async zrank(key: string, value: any): Promise<number | null> {
    const serialized = stringify(value);
    const rank = await this.client.zrank(key, serialized);
    return rank !== null ? rank : null;
  }





  /**
   * 关闭连接（一般不需要手动调）
   */
  async disconnect(): Promise<void> {
    await redisConnection.disconnect();
  }
}

// 导出单个工具实例
const redisUtil = new RedisUtil();
export default redisUtil;
